
/**
 * @Title: PushtaskServiceImpl.java
 * @Package com.py.credit.service.impl
 * @Description: TODO
 * Copyright: Copyright (c) 2020
 * Company:金电联行(江苏)信息技术有限公司
 * @author Comsys-jdzc
 * @date 2020年11月10日 上午10:14:18
 * @version V1.0
 */

package com.py.credit.service.impl;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.py.credit.common.logs.AccessLogger;
import com.py.credit.common.logs.ExceptionLogger;
import com.py.credit.common.rest.RestServiceResult;
import com.py.credit.dao.BatchLogDao;
import com.py.credit.dao.PushtaskServiceDao;
import com.py.credit.entity.BatchFile;
import com.py.credit.entity.BatchLog;
import com.py.credit.entity.Column;
import com.py.credit.entity.SysUser;
import com.py.credit.entity.Table;
import com.py.credit.entity.TableResult;
import com.py.credit.entity.common.LogEnum;
import com.py.credit.entity.enums.DataCollectionFieldsEnum;
import com.py.credit.service.BatchLogService;
import com.py.credit.service.ContentService;
import com.py.credit.service.DataCollectionService;
import com.py.credit.service.DataEntryService;
import com.py.credit.service.PushtaskService;
import com.py.credit.service.RemoteBaseService;
import com.py.credit.service.StepLogService;
import com.py.credit.service.TableService;
import com.py.credit.service.WriteLogsService;
import com.py.credit.service.excel.read.service.ExcelReadService;
import com.py.credit.service.excel.read.service.InspectDataStyleService;
import com.py.credit.utils.UuidUtil;
import com.py.framework.core.common.Page;
import com.py.framework.core.entity.SysUserEntity;

/**
 * @ClassName: PushtaskServiceImpl
 * @Description: TODO(这里用一句话描述这个类的作用)
 * @author jdzc
 * @date 2020年11月10日 上午10:14:18
 *
 */
@Service
public class PushtaskServiceImpl implements PushtaskService {
	private final static long DAY_MILL_SECONDS = 24 * 60 * 60 * 1000L;

	private final static int MILL_SEC = 1000;

	private final static int NUM_5000 = 5000;

	private final static String CHECKREPEAT_NO = "N";

	@Autowired
	private BatchLogService batchLogService;

	@Autowired
	private ExcelReadService excelReadService;

	@Autowired
	private StepLogService stepLogService;

	@Autowired
	@Qualifier("default")
	private InspectDataStyleService inspectDataStyleService;

	@Autowired
	private WriteLogsService writeLogsService;

	@Autowired
	private TableService tableServcie;

	@Autowired
	private DataEntryService dataEntryService;

	@Autowired
	private RemoteBaseService remoteBaseService;

	@Autowired
	private ContentService contentService;

	@Autowired
	private DataCollectionService dataCollectionService;

	@Autowired
	private PushtaskServiceDao pushtaskServiceDao;

	@Autowired
	BatchLogDao batchLogDao;

	@Override
	public Map<String, String> run() {
		Map<String, String> mapresult = new HashMap<String, String>();
		BatchFile batchFile = null;
		long startTimeMill = System.currentTimeMillis();
		try {

			List<Map<String, Object>> result = pushtaskServiceDao.getData();
			List<String> A000003 = result.stream().map(e -> String.valueOf(e.get("A000003")))
					.collect(Collectors.toList());

			Map<String, Object> resultMap = readExcelData(result);

			long endTimeMill = System.currentTimeMillis();
			AccessLogger.info("数据采集总耗时", "", "", "数据采集总耗时" + (endTimeMill - startTimeMill) + "ms");
			mapresult.put("success", "录入成功，已入库");

			pushtaskServiceDao.updateStatus(A000003);

			return mapresult;
		} catch (Exception e) {
			ExceptionLogger.error("PushtaskServiceImpl#run", "前置机数据推送定时任务异常！ERROR：" + e.getMessage(), e);
			stepLogService.addStepLog(batchFile.getBatchId(), "系统异常: 详情请查阅日志。");
			batchLogService.modifyBatchLog(batchFile.getBatchId(), LogEnum.EX_RESULT_F, 0, 0, 0, 0, 0, LogEnum.YWC);

			ExceptionLogger.error("未完成日志处理异常", e.getMessage(), e);
			mapresult.put("fail", batchFile.getBatchId());
			return mapresult;
		}

	}
	@Transactional
	private Map<String, Object> readExcelData(List<Map<String, Object>> listDataMap) throws IOException {
		// 是否使用内存表模式 默认为否
		boolean userMemory = true;
		boolean reStart = true;
		// 是否需要验重
		boolean checkRepeat = true;

		int i = 0;

		int totalCount = 0;
		int waitCount = 0;
		int totalDuplicationCount = 0;
		Map<String, Object> checkResultMap = null;
		// 获取错误信息
		String errorMess = null;
		int errorCount = 0;
		int start = 0;
		int end = 0;
		Map<String, Object> resultMap = new HashMap<>();
		int allRowNum = listDataMap.size();
		String tableDes = "t_100000460009_jnuqj847ju";
		String tableName = null;
		BatchLog batchLog = new BatchLog();
		batchLog.setId(UuidUtil.getInstance().getUUid().toString());
		Table table = tableServcie.queryCubeById(210097);
		// 添加批次日志
		batchLogDao.addBatchLog(batchLog.getId(), table.getTableId(), "0", table.getRootId(), 51l, 1l, LogEnum.WCL,
				null);

		// 获取使用的目录版本
		Integer contentId = pushtaskServiceDao.getcontentId();
		TableResult tableResult = contentService.getTableColumns(210097, contentId, "210097_51");

		List<Column> columns = tableResult.getColumns();
		// 数据大于1000条使用内存表方式
		
			userMemory = true;
			// 生成临时表表名
			String time = new SimpleDateFormat("yyyyMMdd").format(new java.util.Date());
			String head = String.format("%09d", System.currentTimeMillis() % DAY_MILL_SECONDS);
			String body = String.format("%03d", Thread.currentThread().getId());
			String foot = String.format("%04d", ThreadLocalRandom.current().nextInt(MILL_SEC));
			tableName = tableDes + "_temp_" + time + head + body + foot;
			// 创建临时表
			dataEntryService.createTempTable(tableName, columns);
	

		int size = listDataMap.size();

		// 数据重复性校验
		Map<String, Object> duplicationCheck = inspectDataStyleService.duplicationCheck(listDataMap, table, columns,
				userMemory, checkRepeat);
		long duplicationEndTimeMill = System.currentTimeMillis();
		String duplicationMess = (String) duplicationCheck.get("duplicationMess");
		int duplicationCount = (int) duplicationCheck.get("duplicationCount");
		if (duplicationCount != 0) {
			totalDuplicationCount += duplicationCount;

		}
		batchLogService.modifyBatchLog(batchLog.getId(), LogEnum.EX_RESULT_P, size,
				totalCount - totalDuplicationCount - errorCount, errorCount, totalDuplicationCount, waitCount,
				LogEnum.YWC);

		long dataStartTimeMill = System.currentTimeMillis();
		//判断数据是否存在，存在就更新，不存在在录入临时表
		 for (Iterator<Map<String, Object>> it = listDataMap.listIterator(); it.hasNext(); ) {
	            i++;
	            Map<String, Object> next = it.next();                        
	           Integer count = pushtaskServiceDao.isexist(String.valueOf(next.get("A000003")),String.valueOf(next.get("A000002")));
	           if(count>0) {
	        	 
//	        	   //更新实体表数据
//	        	   pushtaskServiceDao.updateZtbData(String.valueOf(next.get("A000001")),String.valueOf(next.get("qylx")),String.valueOf(next.get("JYZT")),String.valueOf(next.get("DZ")),String.valueOf(next.get("FDDBR")),
//	        			   String.valueOf(next.get("DJJG")),String.valueOf(next.get("ZCZB")),String.valueOf(next.get("CLRQ")),String.valueOf(next.get("hzrq")),String.valueOf(next.get("YXQ")),String.valueOf(next.get("yxqz")),
//	        			  String.valueOf( next.get("JYFW")),String.valueOf(next.get("HYDM")),String.valueOf(next.get("ZCZBBZ")),String.valueOf(next.get("A000003")));
//	        	 
//	        	   //更新unique数据
//	        	   pushtaskServiceDao.updateUniqueData(String.valueOf(next.get("A000001")),String.valueOf(next.get("A000003")));
//	        	 
	        	   it.remove();
	           }       
	        }
		
		//将数据录入临时表
		dataEntryService.addDataToTemp(listDataMap, table, batchLog, columns, tableName);

		long dataEndTimeMill = System.currentTimeMillis();
		AccessLogger.info("数据采集数据入库耗时", "", "", "数据采集数据入库耗时" + (dataEndTimeMill - dataStartTimeMill) + "ms");
		totalCount += size;

		
			long memoryStartTimeMill = System.currentTimeMillis();
			try {
				// 更新数据状态，MD5重复的数据标记为R
				if (checkRepeat) {
					stepLogService.addStepLog(batchLog.getId(), "开始临时表数据同步。");
					dataEntryService.updateStatus(tableName, tableDes);
				}
				// 数据拷贝，把临时表的数据同步到实体表中
				stepLogService.addStepLog(batchLog.getId(), "开始数据同步传输。");
				dataEntryService.copyData(tableName, tableDes, columns);
				stepLogService.addStepLog(batchLog.getId(), "结束数据同步传输。");
				// 获取临时表重复数据数量
				if (checkRepeat) {
					int c = dataEntryService.countDataNum(tableName, "R");
					// 重复数相加
					totalDuplicationCount = totalDuplicationCount + c;
				}
			} catch (Exception e) {
				ExceptionLogger.error("UntreatedFileShedule#readExcelData",
						"临时表数据同步至实体表异常！临时表:" + tableName + ",实体表:" + tableDes + ",ERROR:" + e.getMessage(), e);
				stepLogService.addStepLog(batchLog.getId(), "临时表数据同步至实体表异常!");
			} finally {
				// 删除临时表
				dataEntryService.dropTempTable(tableName);
				stepLogService.addStepLog(batchLog.getId(), "结束临时表数据同步。");
			}
			long memoryEndTimeMill = System.currentTimeMillis();
			AccessLogger.info("数据采集数据临时表处理耗时", "", "",
					"数据采集临时表处理耗时" + (memoryEndTimeMill - memoryStartTimeMill) + "ms");
		
		// 数据总量
		resultMap.put("totalCount", totalCount);
		// 重复数量
		resultMap.put("totalDuplicationCount", totalDuplicationCount);
		// 待关联数据量
		resultMap.put("waitCount", waitCount);
		// 未通过校验数量
		resultMap.put("errorCount", errorCount);
		return resultMap;

	}

}
